Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 5 Das Klassendesign (Teil 2)
  gp 5.1 Statische Klassenkomponenten
    gp 5.1.1 Die Realisierung eines Objektzählers
    gp 5.1.2 Zugriff auf statische Komponenten
    gp 5.1.3 Statische Klassenvariable in der Klasse »Circle«
    gp 5.1.4 Klassenspezifische Methoden
    gp 5.1.5 Statische Methoden in der Klasse »Circle«
    gp 5.1.6 Statische Klasseninitialisierer
    gp 5.1.7 Zusammenfassung
  gp 5.2 Delegaten
    gp 5.2.1 Einführung in das Prinzip der Delegaten
    gp 5.2.2 Zusammenfassung der Arbeitsschritte
    gp 5.2.3 Vereinfachter Aufruf eines Delegaten
  gp 5.3 Ereignisse eines Objekts
    gp 5.3.1 Ergänzung eines Ereignisses in einer Ereignisquelle
    gp 5.3.2 Die Behandlung eines Ereignisses im Ereignisempfänger
    gp 5.3.3 Ereignisse mit Übergabeparameter
    gp 5.3.4 Die Handles-Klausel
    gp 5.3.5 Die Registrierung eines Ereignishandlers mit »AddHandler«
    gp 5.3.6 Zusammenfassung
  gp 5.4 Strukturen – eine Sonderform der Klassen
    gp 5.4.1 Die Definition einer Struktur
    gp 5.4.2 Initialisieren einer Struktur
    gp 5.4.3 Ereignisse in einer Struktur
    gp 5.4.4 Änderung der Klasse »Circle«
    gp 5.4.5 Zusammenfassung der Unterscheidungsmerkmale Klasse – Struktur
  gp 5.5 Enumerationen (Aufzählungen)
    gp 5.5.1 Alle Mitglieder einer Aufzählung durchlaufen
  gp 5.6 Referenz- und Wertetypen
    gp 5.6.1 Typumwandlung mit Boxing
    gp 5.6.2 Die Unboxing-Konvertierung
    gp 5.6.3 Zusammenfassung
  gp 5.7 Namensräume (Namespaces)
    gp 5.7.1 Zugriff auf Namespaces
    gp 5.7.2 Die »Imports«-Anweisung
    gp 5.7.3 Aliasnamen zur Vermeidung von Mehrdeutigkeiten
    gp 5.7.4 Aufrufe mit »Global« umleiten
    gp 5.7.5 Namespaces festlegen
    gp 5.7.6 Zusammenfassung


Galileo Computing

5.2 Delegaten  downtop


Galileo Computing

5.2.1 Einführung in das Prinzip der Delegaten  downtop

Das Prinzip der Delegaten ist nicht ganz neu, wohl aber der Begriff an sich. »Delegate« ist das englische Wort für »delegieren« – etwa »weiterleiten«. Tatsächlich leitet ein Delegat weiter, er leitet nämlich einen Methodenaufruf an eine bestimmte Methode weiter.

Die Technik, die sich dahinter verbirgt, wird in der Sprache C auch als Funktionszeiger bezeichnet. Zeigertechnik und .NET – das passt eigentlich nicht zusammen. Die Zeigertechnik – so interessant sie auch sein mag – birgt einige Nachteile in sich: Sie ist schwierig zu lernen, sie ist sehr komplex, die Programme sind zu kompliziert. Ein falscher Einsatz führt nicht selten zu Speicherzugriffsfehlern und damit zum Absturz eines laufenden Programms. Nicht umsonst haben die .NET-Entwickler (und auch die von Java) die Zeigertechnologie gemieden wie der Teufel das Weihwasser.

Dennoch gibt es Aufgabenstellungen, bei denen kein Weg an der Zeigertechnik vorbeiführt – auch nicht unter .NET, wenn auch in einer nicht sofort offensichtlichen Form. Wie Sie wissen, basiert ausnahmslos alles im .NET Framework auf Objekten. Da verwundert es nicht, dass auch die Methodenzeiger in ein Objekt verpackt und als Delegat bezeichnet ihren Weg in die Laufzeitumgebung finden.


Ein Delegat ist ein Objekt, das den Zeiger auf eine Objektmethode beschreibt.


Bevor wir uns mit den Details von Delegaten beschäftigen, wollen wir uns zunächst an einem einfachen Beispiel die grundsätzliche Arbeitsweise verdeutlichen.

Die Operation, die von diesem Code ausgeführt wird, ist recht einfach: Der Anwender gibt zwei Zahlen an der Konsole ein und hat anschließend die Wahl, ob beide Zahlen addiert oder subtrahiert werden sollen. Das Resultat der Operation wird abhängig von der Wahl des Anwenders an der Konsole ausgegeben.


' --------------------------------------------------------------
' Beispiel: ...\Kapitel 5\EinfacherDelegat
' --------------------------------------------------------------
' Definition des Delegaten
Public Delegate Function ProcessOperation(ByVal dblVar1 As Double, _
ByVal dblVar2 As Double) As Double
Module Module1
Sub Main()
' Variable vom Typ des Delegaten
Dim process As ProcessOperation
' Eingabe der Operanden
Console.Write("Geben Sie den ersten Operanden ein: ")
Dim input1 As Double = Console.ReadLine
Console.Write("Geben Sie den zweiten Operanden ein: ")
Dim input2 As Double = Console.ReadLine
' Wahl der Operation
Console.Write("Welche Operation wollen Sie ausführen?")
Console.WriteLine("Addition – (A)")
Console.WriteLine("Subtraktion – (S)")
Dim wahl As String = Console.ReadLine().ToUpper()
' in Abhängigkeit von der Wahl des Anwenders wird die
' Variable 'process' mit einem Zeiger auf die
' auszuführende Methode initialisiert
If wahl = "A" Then
process = New ProcessOperation(AddressOf Addition)
ElseIf (wahl = "S") Then
process = New ProcessOperation(AddressOf Subtraktion)
Else
Console.Write("Ungültige Eingabe")
Console.ReadLine()
Return
End If
' Aufruf der Operation 'Addition' oder 'Subtraktion'
' über den Delegaten
Dim result As Double = process(input1, input2)
Console.WriteLine("----------------------------------")
Console.Write("Ergebnis = {0}", result)
Console.ReadLine()
End Sub
Public Function Addition(ByVal x As Double, _
ByVal y As Double) As Double
Return x + y
End Function
Public Function Subtraktion(ByVal x As Double, _
ByVal y As Double) As Double
Return x – y
End Function
End Module

In Module1 sind neben dem obligatorischen Einstiegspunkt in die Laufzeit zwei Methoden definiert, die aus Main heraus aufgerufen werden und die beiden Operationen Addition und Subtraktion beschreiben.

Die Wahl, ob die beiden Zahlen addiert oder subtrahiert werden sollen, trifft der Anwender durch die Eingabe von A oder S an der Konsole. Um die Eingabe in Kleinschreibweise ebenfalls zu berücksichtigen, wird die Eingabe mit der Methode ToUpper der Klasse String in Großschreibweise umgewandelt.


Dim wahl As String = Console.ReadLine().ToUpper()

Nachdem der Anwender seine Wahl getroffen hat, muss zuerst überprüft werden, wie diese ausgefallen ist, um entsprechend im Programmcode zu reagieren. Vermutlich hätten Sie eine solche Aufgabenstellung bisher wie folgt gelöst:


Dim result As Double
If wahl = "A" Then
result = Addition(input1, input2)
ElseIf wahl = "S" Then
result = Subtraktion(input1, input2)
End If

Es gibt keinen Zweifel daran, dass diese Implementierung natürlich auch zum richtigen Ergebnis führt.

Nun betrachten wir die entscheidenden Anweisungen der Lösung im Beispiel EinfacherDelegat:


If wahl = "A" Then
process = New ProcessOperation(AddressOf Addition)
ElseIf (wahl = "S") Then
process = New ProcessOperation(AddressOf Subtraktion)
...
End If
Dim result As Double = process(input1, input2)

Der Unterschied ist jetzt, dass wir das Ergebnis der Addition bzw. Subtraktion nun nicht mehr in den beiden Anweisungsblöcken der If-Struktur abrufen, sondern außerhalb derselben. Da aber außerhalb der If-Struktur die Wahl des Anwenders nicht bekannt sein kann, stehen wir vor der Frage, wie es möglich ist, eine Methode an einem Allgemeinplatz dynamisch aufrufen zu können. Die Antwort darauf ist prinzipiell nicht schwierig: Wir müssen einen Verweis auf die aufzurufende Methode in einer Variablen speichern, der später an einer beliebigen Stelle im Code ausgewertet werden kann.

Bisher kennen wir Verweise nur im Zusammenhang mit Objekten. Mit Objektverweisen werden zusammenhängende Datenblöcke im Hauptspeicher adressiert, in denen die Zustandsdaten eines ganz bestimmten Objekts beschrieben werden. Ein Verweis auf Programmcode ist im Grunde genommen nicht anders, zeigt aber auf Bytesequenzen, die anders interpretiert werden müssen – nämlich als ausführbarer Programmcode. Damit ist auch klar, dass ein Verweis auf Code anders definiert werden muss als der uns gebräuchliche Verweis auf Datenblöcke. Aus diesem Grund wurden in .NET die Delegaten eingeführt.

Wie schon oben erwähnt, kapselt ein Delegat den Zeiger auf eine Methode. Wir wissen zudem, dass .NET nur Objekte kennt. Sehen wir uns jetzt an, wie die Konstrukteure von Visual Basic 2005 diese beiden Anforderungen konzeptuell gelöst haben.

Im Code des Beispiels EinfacherDelegat wird mit


Public Delegate Function ProcessOperation(ByVal dblVar1 As Double, _
ByVal dblVar2 As Double) As Double

ein Delegat definiert. Diese Definition erinnert ein wenig an die Methodensignatur einer Methode namens ProcessOperation, die zwei Parameter vom Typ Double empfängt und als Rückgabewert einen Double liefert – nur ergänzt um das Schlüsselwort Delegate.

Ein Delegat kapselt den Zeiger auf eine Methode oder mit anderen Worten, er steht für einen beliebigen Methodenaufruf. Ganz beliebig ist der Methodenaufruf allerdings nicht, denn jede Methode hat eine exakt definierte Parameterliste mit Parametern eines bestimmten Typs. Ein Delegat beschreibt einen Zeiger auf eine Methode, wobei die Typen der Parameterliste der Methode, auf die der Delegat zeigt, mit der Parameterliste der Delegate-Definition übereinstimmen müssen.

In unserem Beispiel werden in der Parameterliste des Delegaten ProcessOperation zwei Parameter vom Typ Double aufgeführt. Damit wäre dieser Delegat in der Lage, jede x-beliebige Methode eines x-beliebigen Objekts aufzurufen – vorausgesetzt, die Methode definiert eine Parameterliste, die genau zwei Double-Argumente erwartet.


Die Parameterliste einer Delegate-Definition entspricht der Parameterliste der Methode, auf die der Delegat zeigt.


Das ist nicht die einzige Bedingung, die an die Methode gestellt wird, die ein Delegat beschreibt. Der Rückgabewert spielt eine ebenso wichtige Rolle. Im Beispiel des Delegaten ProcessOperation muss die Methode in jedem Fall einen Rückgabewert vom Typ Double haben. Weil sowohl Parameterliste als auch Rückgabetyp durch einen Delegaten eindeutig festgelegt werden, spricht man beim Konstrukt eines Delegaten auch von einem typisierten Funktionszeiger.

Nicht jede Methode hat einen Rückgabewert. Beabsichtigen Sie beispielsweise, einen Delegaten zu definieren, der in der Lage ist, einen Zeiger auf sämtliche Methoden zu beschreiben, die parameterlos sind und keinen Rückgabewert haben, sähe die Definition folgendermaßen aus:


Public Delegate Sub MyDelegate()

Sie können die Definition eines Delegaten mit der Definition einer Klasse vergleichen, denn beide beschreiben einen Typ. Um ein konkretes Objekt zu erhalten, muss zuerst eine Variable vom Typ der Klasse deklariert werden – das ist bei einem Delegaten nicht anders. Im Beispiel dient dazu die Anweisung:


Dim process As ProcessOperation

Damit ist die Variable process vom Typ ProcessOperation deklariert, aber noch nicht initialisiert. Mit anderen Worten: process ist ein Delegat und kann auf eine Methode verweisen, die zwei Double-Argumente erwartet und einen Double als Resultat des Aufrufs zurückliefert. In diesem Moment weiß der Delegat allerdings noch nicht, um welche Methode es sich dabei genau handelt.

Die Initialisierung erfolgt – analog zur Instanziierung einer Klasse – mit dem Operator New unter Angabe des Delegatentyps. Dahinter gibt man in runden Klammern unter Hinzuziehung des AddressOf-Operators den Bezeichner der Methode an, die später vom Delegaten aufgerufen werden soll. In unserem Beispiel handelt es sich um


process = New ProcessOperation(AddressOf Addition)

und


process = New ProcessOperation(AddressOf Subtraktion);

Danach ist dem Delegaten bekannt, welche Methode ausgeführt werden soll: entweder Addition oder Subtraktion. Allerdings wird die Methode, auf die der Delegat in Form eines Zeigers verweist, noch nicht sofort gestartet, denn dazu bedarf es eines Anstoßes durch den Aufruf des Delegaten:


Dim result As Double = process(input1, input2)

Der Aufruf erinnert an den Aufruf einer Methode, dabei wird allerdings der Methodenname (hier: Addition bzw. Subtraktion) durch die Variable vom Typ des Delegaten ersetzt. In den Klammern werden die erforderlichen Argumente an die Methode übergeben.


Galileo Computing

5.2.2 Zusammenfassung der Arbeitsschritte  downtop

Um eine aufzurufende Methode erst zur Laufzeit festzulegen, ist das Konstrukt der Delegaten sicherlich sehr interessant. Allerdings ist die syntaktische Realisierung etwas gewöhnungsbedürftig, daher sollen hier die Schritte noch einmal allgemein zusammengefasst werden.

1. Definieren Sie zuerst einen Delegaten, z.  B.:
       
Public Delegate Function ProcessOperation(ByVal dblVar1 _ 
            As Double, ByVal dblVar2 As Double) As Double
Als Modifizierer kommen Private, Protected, Friend und Public in Frage.
2. Deklarieren Sie eine Variable vom Typ des Delegaten, z.  B.:
       
Dim process As ProcessOperation process
3. Erzeugen Sie ein Objekt vom Typ des Delegaten, und übergeben Sie dabei als Argument den Namen der Methode, die vom Delegaten aufgerufen werden soll, z.  B.:
       
 process = new ProcessOperation(AddressOf Addition)
4. Rufen Sie den Delegaten auf, und übergeben Sie dabei die Parameter, die von der Methode empfangen werden sollen, auf die der Delegat zeigt, z.  B.:
       
Dim result As double = process(input1, input2)

Hinweis

Wir haben noch nicht alle Gesichtspunkte erörtert, die im Zusammenhang mit den Delegaten von programmiertechnischem Interesse sind. Wenn wir uns jedoch weiter mit diesen Konstrukten beschäftigen wollen, sollten mehr Grundsätze der objektorientierten Programmierung bekannt sein. Daher wird das Thema an dieser Stelle unterbrochen und in Kapitel 7 noch einmal aufgegriffen.



Galileo Computing

5.2.3 Vereinfachter Aufruf eines Delegaten  toptop

Neben der gezeigten Notation gibt es unter Visual Basic 2005 eine weitere, einen Delegaten zu instanziieren und ihm gleichzeitig die auszuführende Methode anzugeben. Diese Neuerung ist etwas einfacher in der Handhabung. Sie können nämlich anstelle der Anweisung


Dim process As ProcessOperation = _
New ProcessOperation(AddressOf Addition)

auch wie folgt codieren:


Dim process As ProcessOperation = AddressOf Addition

Auch für den Aufruf des Delegaten gibt es mit


Dim result As Double = p.Invoke(input1, input2)

eine zweite Alternative.

 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de